package com.example.inboxdemo.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.inboxdemo.pojo.dbo.InboxMsgDO;
import com.example.inboxdemo.pojo.dbo.UserStudioRelationDO;
import com.example.inboxdemo.pojo.entity.PublishDTO;
import com.example.inboxdemo.pojo.entity.Scope;
import com.example.inboxdemo.service.IInboxMsgService;
import com.example.inboxdemo.service.IMsgSendService;
import com.example.inboxdemo.service.IUserStudioRelationService;
import lombok.RequiredArgsConstructor;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class MsgSendServiceImpl implements IMsgSendService {
    private final RedissonClient redissonClient;
    private final IUserStudioRelationService userStudioRelationService;
    private final IInboxMsgService inboxMsgService;

    @Override
    public void publish(PublishDTO publishDTO) {
        // 持久化数据到db（由于Redis的发布订阅模式，可能存在消息丢失风险，且实时站内信只会发送给在线的用户，
        // 未在线的用户登录后也需要看到离线期间的站内信，以及站内信管理功能的需要，所以站内信数据需要持久化）
        inboxMsgService.save(convert(publishDTO));
        Scope scope = publishDTO.getScope();
        if (scope == Scope.EVERYONE) {
            publishDTO.setTitle("广播消息: " + publishDTO.getTitle());
            // 向所有在线用户发送实时站内信
            redissonClient
                    .getTopic("inbox_broadcast_msg_topic")
                    .publish(publishDTO);
        } else if (scope == Scope.STUDIO) {
            publishDTO.setTitle("工作室消息: " + publishDTO.getTitle());
            // 查询工作室下所有用户列表，发送信息到每个用户
            List<String> userIds = userStudioRelationService.list(
                            new LambdaQueryWrapper<UserStudioRelationDO>()
                                    .eq(UserStudioRelationDO::getStudioId, publishDTO.getTarget())
                    )
                    .stream()
                    .map(UserStudioRelationDO::getUserId)
                    .collect(Collectors.toList());
            for (String userId : userIds) {
                // 将目标设置为用户id，在InboxUserTopicListener内用到
                publishDTO.setTarget(userId);
                redissonClient
                        .getTopic("inbox_topic_user_" + userId)
                        .publish(publishDTO);
            }
        } else if (scope == Scope.USER) {
            publishDTO.setTitle("个人消息: " + publishDTO.getTitle());
            redissonClient
                    .getTopic("inbox_topic_user_" + publishDTO.getTarget())
                    .publish(publishDTO);
        } else {
            throw new IllegalArgumentException("不支持的发送范围");
        }

    }

    private InboxMsgDO convert(PublishDTO publishDTO) {
        InboxMsgDO inboxMsgDO = new InboxMsgDO();
        inboxMsgDO.setTitle(publishDTO.getTitle());
        inboxMsgDO.setContent(publishDTO.getContent());
        inboxMsgDO.setScope(publishDTO.getScope());
        inboxMsgDO.setTargetId(publishDTO.getTarget());
        return inboxMsgDO;
    }
}
